
use std::{rc::Rc, cell::RefCell, sync::{Arc, Mutex}};

use jvm_rust::raw;

use crate::{native, rtda::{Frame, heap::{self, Class, ClassLoader, ArrayObject, string_pool}, OperandStack, ExtraType, Object, Slot}, instructions::base};
static JL_CLASS: &'static str = "java/lang/Class";
pub fn init() {
    native::register(JL_CLASS, "getPrimitiveClass", "(Ljava/lang/String;)Ljava/lang/Class;", get_primitive_class);
    native::register(JL_CLASS, "getName0", "()Ljava/lang/String;", get_name0);
    native::register(JL_CLASS, "desiredAssertionStatus0", "(Ljava/lang/Class;)Z", desired_assertion_status0);
	native::register(JL_CLASS, "isInterface", "()Z", is_interface);
	native::register(JL_CLASS, "isPrimitive", "()Z", is_primitive);
	native::register(JL_CLASS, "getDeclaredFields0", "(Z)[Ljava/lang/reflect/Field;", get_declared_field0);
	native::register(JL_CLASS, "forName0", "(Ljava/lang/String;ZLjava/lang/ClassLoader;Ljava/lang/Class;)Ljava/lang/Class;", for_name0);
	native::register(JL_CLASS, "getDeclaredConstructors0", "(Z)[Ljava/lang/reflect/Constructor;", get_declared_constructors0);
	native::register(JL_CLASS, "getModifiers", "()I", get_modifiers);
	native::register(JL_CLASS, "getSuperclass", "()Ljava/lang/Class;", get_superclass);
	native::register(JL_CLASS, "getInterfaces0", "()[Ljava/lang/Class;", get_interfaces0);
	native::register(JL_CLASS, "isArray", "()Z", is_array);
	native::register(JL_CLASS, "getDeclaredMethods0", "(Z)[Ljava/lang/reflect/Method;", get_declared_methods0);
	native::register(JL_CLASS, "getComponentType", "()Ljava/lang/Class;", get_component_type);
	native::register(JL_CLASS, "isAssignableFrom", "(Ljava/lang/Class;)Z", is_assignable_from);
	native::register(JL_CLASS, "getEnclosingMethod0", "()[Ljava/lang/Object;", get_enclosing_method0);
	native::register(JL_CLASS, "getDeclaringClass0", "()Ljava/lang/Class;", get_declaring_class0);
	native::register(JL_CLASS, "getProtectionDomain0", "()Ljava/security/ProtectionDomain;", get_protection_domain0);
    native::register(JL_CLASS, "isInstance", "(Ljava/lang/Object;)Z", is_instance);
}

// static native Class<?> getPrimitiveClass(String name);
// (Ljava/lang/String;)Ljava/lang/Class;
// getPrimitiveClass()是静态方法。先从局部变量表中拿到类名，这是个Java字符串，需要把它转成Rust字符串。
// 基本类型的类已经加载到了方法区中，直接调用类加载器的LoadClass()方法获取即可。
fn get_primitive_class(frame: Rc<RefCell<Frame>>) {
    let name_obj = frame.borrow().get_local_vars().borrow().get_ref(0);
    let name = string_pool::rs_string(name_obj.unwrap());
    let loader = frame.borrow().get_method().get_class().get_class_loader().unwrap();
    let class = loader.lock().unwrap().load_class(name).get_j_class();

    frame.borrow().get_operand_stack().borrow_mut().push_ref(class);
}

// private native String getName0();
// ()Ljava/lang/String;
fn get_name0(frame: Rc<RefCell<Frame>>) {
    // 获取this引用，等同于get_ref(0),此时获取到的this为类对象引用j_class
    let this = frame.borrow().get_local_vars().borrow().get_this().unwrap();
    // 通过获取j_class中的extra获取此类的class结构体
    if let ExtraType::Class(class) = unsafe { &*this }.get_extra().unwrap() {
        // 这里需要的是java.lang.Object这样的类名，而非java/lang/Object
        let name = class.java_name();
        let name_obj = string_pool::j_string(&mut class.get_class_loader().unwrap().lock().unwrap(), &name);

        frame.borrow().get_operand_stack().borrow_mut().push_ref(Some(name_obj));
    } else {
        panic!("ExtraType is not Class");
    }
}

// private static native boolean desiredAssertionStatus0(Class<?> clazz);
// (Ljava/lang/Class;)Z
// TODO 断言处理，暂不处理
fn desired_assertion_status0(frame: Rc<RefCell<Frame>>) {
    frame.borrow().get_operand_stack().borrow_mut().push_boolean(false); // false
}

// public native boolean isInterface();
// ()Z
fn is_interface(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    let this = vars.borrow().get_this().unwrap();
    if let Some(ExtraType::Class(class)) = unsafe { &*this }.get_extra() {
        let stack = frame.borrow().get_operand_stack();
        stack.borrow_mut().push_boolean(class.is_interface());
    }
}

// public native boolean isPrimitive();
// ()Z
fn is_primitive(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    let this = vars.borrow().get_this().unwrap();
    if let Some(ExtraType::Class(class)) = unsafe { &*this }.get_extra() {
        let stack = frame.borrow().get_operand_stack();
        stack.borrow_mut().push_boolean(class.is_primitive());
    }
}

/*
Field(Class<?> declaringClass,
      String name,
      Class<?> type,
      int modifiers,
      int slot,
      String signature,
      byte[] annotations)
*/
static FIELD_CONSTRUCTOR_DESCRIPTOR: &'static str = "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;IILjava/lang/String;[B)V";

// private native Field[] getDeclaredFields0(boolean publicOnly);
// (Z)[Ljava/lang/reflect/Field;
fn get_declared_field0(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    let class_obj = vars.borrow().get_this().unwrap();
    let public_only = vars.borrow().get_boolean(1);

    if let Some(ExtraType::Class(class)) = unsafe { &*class_obj }.get_extra() {
        let fields = class.get_fields(public_only);
        let field_count = fields.len();
        let class_loader = frame.borrow().get_method().get_class().get_class_loader().unwrap();
        // if class_loader.try_lock().is_err() {
        //     println!("classloader此时有占用！11")
        // }
        let field_class = class_loader.lock().unwrap().load_class("java/lang/reflect/Field".to_string());
        let field_arr = Class::new_array(field_class.array_class(), field_count);
        let field_arr = Box::into_raw(Box::new(field_arr));

        let stack = frame.borrow().get_operand_stack();
        stack.borrow_mut().push_ref(Some(field_arr));

        if field_count > 0 {
            let thread = frame.borrow().get_thread();
            let field_objs = unsafe { &mut *field_arr }.array().refs();
            let field_constructor = field_class.get_constructor(FIELD_CONSTRUCTOR_DESCRIPTOR).unwrap();

            for i in 0..field_count {
                let rs_field = fields[i].clone();
                let mut field_obj = Class::new_object(field_class.clone());
                field_obj.set_extra(Some(ExtraType::Field(rs_field.clone())));
                let field_obj = Box::into_raw(Box::new(field_obj));
                field_objs[i] = Some(field_obj);

                let mut ops = OperandStack::new_operand_stack(8);
                // this
                ops.push_ref(Some(field_obj));
                // declaringClass
                ops.push_ref(Some(class_obj));
                // name
                ops.push_ref(Some(string_pool::j_string(&mut class_loader.lock().unwrap(), &rs_field.get_name())));
                // type
                ops.push_ref(rs_field.get_type().get_j_class());
                // modifiers
                ops.push_int(rs_field.get_access_flags() as i32);
                // slot
                ops.push_int(rs_field.get_slot_id() as i32);
                // signature
                ops.push_ref(get_signature_str(class_loader.clone(), &rs_field.get_signature()));
                // annotations
                ops.push_ref(to_byte_arr(class_loader.clone(), rs_field.get_annotation_data()));
                let shim_frame = Frame::new_shim_frame(thread.clone(), Rc::new(RefCell::new(ops)));
                thread.lock().unwrap().push_frame(shim_frame);

                // init fieldObj
                let shim_frame = thread.lock().unwrap().current_frame();
                base::invoke_method(shim_frame, field_constructor.clone());
            }
            
        }
    }
}

// private static native Class<?> forName0(String name, boolean initialize,
//                                         ClassLoader loader,
//                                         Class<?> caller)
//     throws ClassNotFoundException;
// (Ljava/lang/String;ZLjava/lang/ClassLoader;Ljava/lang/Class;)Ljava/lang/Class;
fn for_name0(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    let j_name = vars.borrow().get_ref(0).unwrap();
    let initialize = vars.borrow().get_boolean(1);
    // let j_loader = vars.borrow().get_ref(2);

    let rs_name = string_pool::rs_string(j_name).replace( ".", "/");
    let rs_class = frame.borrow().get_method().get_class().get_class_loader().unwrap().lock().unwrap().load_class(rs_name);
    let j_class = unsafe { &*rs_class }.get_j_class();

    if initialize && !unsafe { &*rs_class }.init_started() {
        // undo forName0
        let thread = frame.borrow().get_thread();
        frame.borrow_mut().set_next_pc(thread.lock().unwrap().get_pc() as usize);
        // init class
        base::init_class(thread, rs_class );
    } else {
        let stack = frame.borrow().get_operand_stack();
        stack.borrow_mut().push_ref(j_class);
    }
}


/*
Constructor(Class<T> declaringClass,
            Class<?>[] parameterTypes,
            Class<?>[] checkedExceptions,
            int modifiers,
            int slot,
            String signature,
            byte[] annotations,
            byte[] parameterAnnotations)
}
*/
static CONSTRUCTOR_CONSTRUCTOR_DESCRIPTOR: &'static str = "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;IILjava/lang/String;[B[B)V";

// private native Constructor<T>[] getDeclaredConstructors0(boolean publicOnly);
// (Z)[Ljava/lang/reflect/Constructor;
fn get_declared_constructors0(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    let class_obj = vars.borrow().get_this().unwrap();
    let public_only = vars.borrow().get_boolean(1);

    if let Some(ExtraType::Class(class)) = unsafe { &*class_obj }.get_extra() {
        let constructors = class.get_constructors(public_only);
        let constructor_count = constructors.len();

        let class_loader = frame.borrow().get_method().get_class().get_class_loader().unwrap();

        // if class_loader.try_lock().is_err() {
        //     println!("classloader此时有占用！get_declared_constructors0")
        // }

        let constructor_class = class_loader.lock().unwrap().load_class("java/lang/reflect/Constructor".to_string());
        let constructor_arr = Class::new_array(constructor_class.array_class(), constructor_count);
        let constructor_arr = Box::into_raw(Box::new(constructor_arr));
        
        let stack = frame.borrow().get_operand_stack();
        stack.borrow_mut().push_ref(Some(constructor_arr));
        if constructor_count > 0 {
            let thread = frame.borrow().get_thread();
            if let heap::ArrayObject::Object(constructor_objs) = unsafe { &mut *constructor_arr }.array() {
                let constructor_init_method = unsafe { &*constructor_class }.get_constructor(CONSTRUCTOR_CONSTRUCTOR_DESCRIPTOR).unwrap();

                for i in 0..constructor_count {
                    let constructor = constructors[i].clone();
                    let mut constructor_obj = Class::new_object(constructor_class.clone());
                    constructor_obj.set_extra(Some(ExtraType::Method(constructor.clone())));
                    let constructor_obj = Box::into_raw(Box::new(constructor_obj));
                    constructor_objs[i] = Some(constructor_obj);

                    let mut ops = OperandStack::new_operand_stack(9);
                    // this
                    ops.push_ref(Some(constructor_obj));
                    // declaringClass
                    ops.push_ref(Some(class_obj));
                    // parameterTypes
                    ops.push_ref(Some(to_class_arr(class_loader.clone(), constructor.parameter_types())));
                    // checkedExceptions
                    ops.push_ref(Some(to_class_arr(class_loader.clone(), constructor.exception_types())));
                    // modifiers
                    ops.push_int(constructor.get_access_flags() as i32);
                    // todo slot
                    ops.push_int(0);

                    // signature
                    ops.push_ref(get_signature_str(class_loader.clone(), &constructor.get_signature()));
                    // annotations
                    ops.push_ref(to_byte_arr(class_loader.clone(), constructor.get_annotation_data()));
                    // parameterAnnotations
                    ops.push_ref(to_byte_arr(class_loader.clone(), constructor.get_parameter_annotation_data()));
                    let shim_frame = Frame::new_shim_frame(thread.clone(), Rc::new(RefCell::new(ops)));
                    thread.lock().unwrap().push_frame(shim_frame);

                    // init constructorObj
                    let shim_frame = thread.lock().unwrap().current_frame();
                    base::invoke_method(shim_frame, constructor_init_method.clone());
                }
            }
        }
    }
}

// public native int getModifiers();
// ()I
fn get_modifiers(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    let this = vars.borrow().get_this().unwrap();
    if let Some(ExtraType::Class(class)) = unsafe { &*this }.get_extra() {
        let modifiers = class.get_access_flags();

        let stack = frame.borrow().get_operand_stack();
        stack.borrow_mut().push_int(modifiers as i32);
    }
}

// public native Class<? super T> getSuperclass();
// ()Ljava/lang/Class;
fn get_superclass(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    let this = vars.borrow().get_this().unwrap();
    if let Some(ExtraType::Class(class)) = unsafe { &*this }.get_extra() {
        let super_class = class.get_super_class();

        let stack = frame.borrow().get_operand_stack();
        if super_class.is_some() {
            stack.borrow_mut().push_ref(unsafe { &*super_class.unwrap() }.get_j_class())
        } else {
            stack.borrow_mut().push_ref(None);
        }
    }
}

// private native Class<?>[] getInterfaces0();
// ()[Ljava/lang/Class;
fn get_interfaces0(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    let this = vars.borrow().get_this().unwrap();
    if let Some(ExtraType::Class(class)) = unsafe { &*this }.get_extra() {
        let interfaces = class.get_interfaces();
        let class_arr = to_class_arr(class.get_class_loader().unwrap(), interfaces.clone());

        let stack = frame.borrow().get_operand_stack();
        stack.borrow_mut().push_ref(Some(class_arr));
    }
}

// public native boolean isArray();
// ()Z
fn is_array(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    let this = vars.borrow().get_this().unwrap();
    if let Some(ExtraType::Class(class)) = unsafe { &*this }.get_extra() {
        let stack = frame.borrow().get_operand_stack();
        stack.borrow_mut().push_boolean(class.is_array());
    }
}

/*
Method(Class<?> declaringClass,
       String name,
       Class<?>[] parameterTypes,
       Class<?> returnType,
       Class<?>[] checkedExceptions,
       int modifiers,
       int slot,
       String signature,
       byte[] annotations,
       byte[] parameterAnnotations,
       byte[] annotationDefault)
*/
static METHOD_CONSTRUCTOR_DESCRIPTOR: &'static str = "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/Class;[Ljava/lang/Class;IILjava/lang/String;[B[B[B)V";

// private native Method[] getDeclaredMethods0(boolean publicOnly);
// (Z)[Ljava/lang/reflect/Method;
fn get_declared_methods0(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    let class_obj = vars.borrow().get_this().unwrap();
    let public_only = vars.borrow().get_boolean(1);

    if let Some(ExtraType::Class(class)) = unsafe { &*class_obj }.get_extra() {
        let methods = class.get_methods(public_only);
        let method_count = methods.len();

        let class_loader = frame.borrow().get_method().get_class().get_class_loader().unwrap();
        let method_class = class_loader.lock().unwrap().load_class("java/lang/reflect/Method".to_string());
        let method_arr = Class::new_array(method_class.array_class(), method_count);
        let method_arr = Box::into_raw(Box::new(method_arr));

        let stack = frame.borrow().get_operand_stack();
        stack.borrow_mut().push_ref(Some(method_arr));

        if method_count > 0 {
            let thread = frame.borrow().get_thread();
            if let heap::ArrayObject::Object(method_objs) = unsafe { &mut *method_arr }.array() {
                let method_constructor = unsafe { &*method_class }.get_constructor(METHOD_CONSTRUCTOR_DESCRIPTOR).unwrap();

                for i in 0..method_count {
                    let method = methods[i].clone();
                    let mut method_obj = Class::new_object(method_class.clone());
                    method_obj.set_extra(Some(ExtraType::Method(method.clone())));
                    let method_obj = Box::into_raw(Box::new(method_obj));
                    method_objs[i] = Some(method_obj);

                    let mut ops = OperandStack::new_operand_stack(12);
                    // this
                    ops.push_ref(Some(method_obj));
                    // declaringClass
                    ops.push_ref(Some(class_obj));
                    // name
                    ops.push_ref(Some(string_pool::j_string(&mut class_loader.lock().unwrap(), &method.get_name())));
                    // parameterTypes
                    ops.push_ref(Some(to_class_arr(class_loader.clone(), method.parameter_types())));
                    // returnType
                    ops.push_ref(unsafe { &*method.return_type() }.get_j_class());
                    // checkedExceptions
                    ops.push_ref(Some(to_class_arr(class_loader.clone(), method.exception_types())));
                    // modifiers
                    ops.push_int(method.get_access_flags() as i32);
                    // todo slot
                    ops.push_int(0);
                    // signature
                    ops.push_ref(get_signature_str(class_loader.clone(), &method.get_signature()));
                    // annotations
                    ops.push_ref(to_byte_arr(class_loader.clone(), method.get_annotation_data()));
                    // parameterAnnotations
                    ops.push_ref(to_byte_arr(class_loader.clone(), method.get_parameter_annotation_data()));
                    // annotationDefault
                    ops.push_ref(to_byte_arr(class_loader.clone(), method.get_annotation_default_data()));
                    let shim_frame = Frame::new_shim_frame(thread.clone(), Rc::new(RefCell::new(ops)));
                    thread.lock().unwrap().push_frame(shim_frame);

                    // init fieldObj
                    let shim_frame = thread.lock().unwrap().current_frame();
                    base::invoke_method(shim_frame, method_constructor.clone());
                }
            }
        }
    }
}

// public native Class<?> getComponentType();
// ()Ljava/lang/Class;
fn get_component_type(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    let this = vars.borrow().get_this().unwrap();
    if let Some(ExtraType::Class(class)) = unsafe { &*this }.get_extra() {
        let component_class = class.component_class();
        let component_class_obj = unsafe { &*component_class }.get_j_class();

        let stack = frame.borrow().get_operand_stack();
        stack.borrow_mut().push_ref(component_class_obj);
    }
}

// public native boolean isAssignableFrom(Class<?> cls);
// (Ljava/lang/Class;)Z
fn is_assignable_from(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    let this = vars.borrow().get_this().unwrap();
    let cls = vars.borrow().get_ref(1).unwrap();
    let this_extera = unsafe { &*this }.get_extra();
    let cls_extera = unsafe { &*cls }.get_extra();
    if let (Some(ExtraType::Class(this_class)), Some(ExtraType::Class(cls_class))) = (this_extera, cls_extera) {
        let ok = this_class.is_assignable_from(cls_class.as_ref());

        let stack = frame.borrow().get_operand_stack();
        stack.borrow_mut().push_boolean(ok);
    }
}

// private native Object[] getEnclosingMethod0();
// ()[Ljava/lang/Object;
// 返回有关给定类的 EnclosingMethod 属性的信息（如果存在）或 null（如果该类没有封闭方法）。
// 如果非 null，则返回的数组包含三个元素。元素 0 是封闭方法所属的 java.lang.Class，
// 元素 1 和 2 分别是封闭方法名称和描述符的 java.lang.Strings。
fn get_enclosing_method0(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    // jclass
    let this = vars.borrow().get_this().unwrap();
    unsafe {
        let obj = {&*this};
        // unconfirmed 231114 感觉应该是用extra获取原class，先这么用，不行后面再换
        if let Some(ExtraType::Class(class)) = obj.get_extra() {
            if let Some(enclosing_method) = class.get_enclosing_method() {
                let cl = class.get_class_loader().unwrap();
                let object = cl.lock().unwrap().load_class("[Ljava/lang/Object;".to_string());
                // 返回结果Object数组
                let mut array_class = Class::new_array(object, 3);
                let mut array = array_class.array();
                let mut refs = array.refs();
                let em_class = cl.lock().unwrap().load_class(enclosing_method.class_name());
                refs[0] = em_class.get_j_class();
                let (name, descriptor) = enclosing_method.method_name_and_type();
                refs[1] = Some(string_pool::j_string(&mut cl.lock().unwrap(), &name));
                refs[2] = Some(string_pool::j_string(&mut cl.lock().unwrap(), &descriptor));
                // 将结果返回
                let stack = frame.borrow().get_operand_stack();
                let mut slot = Slot::default();
                slot.set_ref(Some(raw!(array_class)));
                stack.borrow_mut().push_slot(slot);
                return;
            }
        }
    }
    // 未查找到返回null
    let stack = frame.borrow().get_operand_stack();
    stack.borrow_mut().push_slot(Slot::default());
}

// 若为顶级类返回null， 内部类返回上个层级类
// private native Class<?> getDeclaringClass0();
// ()Ljava/lang/Class;
fn get_declaring_class0(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    // jclass
    let this = vars.borrow().get_this().unwrap();
    unsafe {
        let obj = {&*this};
        // unconfirmed 231114 感觉应该是用extra获取原class，先这么用，不行后面再换
        if let Some(ExtraType::Class(class)) = obj.get_extra() {
            let class_obj = class.get_j_class();
            let mut slot = Slot::default();
            let class_name = class.get_source_file_class_name();
            match class_name {
                Some(name) if &name != &class.get_name() => {
                    let loader = class.get_class_loader().unwrap();
                    let source_class = loader.lock().unwrap().load_class(name);
                    slot.set_ref(source_class.get_j_class());
                },
                _ => ()
            }
            let stack = frame.borrow().get_operand_stack();
            stack.borrow_mut().push_slot(slot);
        } else {
            panic!("需要测试或修改此处。");
        }
    }
}

// private native java.security.ProtectionDomain getProtectionDomain0();
// ()Ljava/security/ProtectionDomain;
fn get_protection_domain0(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    let this = vars.borrow().get_this().unwrap();
    // panic!("xxxxxxx");
    // TODO 231114 不知道咋弄先返回null
    let stack = frame.borrow().get_operand_stack();
    stack.borrow_mut().push_slot(Slot::default());
}


// 等效于instanceof运算符
// public native boolean isInstance(Object obj);
// (Ljava/lang/Object;)Z
fn is_instance(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    let this = vars.borrow().get_this().unwrap();
    let obj = vars.borrow().get_ref(1);
    let stack = frame.borrow().get_operand_stack();
    // TODO 231212 暂时直接放回true。
    stack.borrow_mut().push_int(1);
    // TODO 231212 应该用下面方法判断，但现在返回结果与用java测试时不同，估计是Unsafe.define_anonymous_class方法定义匿名类时的问题。
    // if let Some(other) = obj {
    //     unsafe {
    //         let this_class = {&*this}.get_extra().unwrap().get_class();
    //         let other_class = {&*other}.get_class();
            
    //         if other_class.is_assignable_from(&this_class) {
    //             stack.borrow_mut().push_int(1);
    //         } else {
    //             stack.borrow_mut().push_int(0);
    //         }
    //     }
    // } else {
    //     stack.borrow_mut().push_boolean(false);
    // }
}


 // class_helper
// []*Class => Class[]
pub fn to_class_arr(loader: Arc<Mutex<ClassLoader>>, classes: Vec<Arc<Class>>) -> *mut Object {
    let arr_len = classes.len();
    let class = loader.lock().unwrap().load_class("java/lang/Class".to_string());
    let class_arr_class = class.array_class();
    let mut class_arr = Class::new_array(class_arr_class, arr_len);

    if arr_len > 0 {
        if let ArrayObject::Object(class_objs) = class_arr.array() {
            for i in 0..arr_len {
                let class = &classes[i];
                class_objs[i] = class.get_j_class();
            }
        }
    }

    Box::into_raw(Box::new(class_arr))
}

pub fn to_byte_arr(loader: Arc<Mutex<ClassLoader>>, rs_bytes: &Vec<u8>) -> Option<*mut Object> {
    if !rs_bytes.is_empty() {
        let j_bytes = cast_u8s_to_i8s(rs_bytes);
        Some(Class::new_byte_array(loader, j_bytes))
    } else {
        None
    }
}

fn cast_u8s_to_i8s(rs_bytes: &Vec<u8>) -> Vec<i8> {
    rs_bytes.into_iter().map(|val| *val as i8).collect()
}

pub fn get_signature_str(loader: Arc<Mutex<ClassLoader>>, signature: &str) -> Option<*mut Object> {
    if signature != "" {
        Some(string_pool::j_string(&mut loader.lock().unwrap(), signature))
    } else {
        None
    }
}





